package com.adopapa.ethexplorer.service;

import java.util.LinkedList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;

import com.adopapa.ethexplorer.domain.BlockInfo;
import com.adopapa.ethexplorer.domain.ContractInfo;
import com.adopapa.ethexplorer.domain.TransactionInfo;
import com.adopapa.ethexplorer.domain.UserInfo;
import com.adopapa.ethexplorer.domain.UserInfo.UserType;
import com.adopapa.ethexplorer.utils.Tools;

/**
 * 查询工具类。
 */
public final class QueryHelper {

	protected static Logger logger = LoggerFactory.getLogger(QueryHelper.class);

	public static PageRequest buildPageRequest(int pageNo, int pageSize, Order... orders) {
		return PageRequest.of(pageNo - 1, pageSize, Sort.by(orders));
	}

	@SuppressWarnings("serial")
	public static Specification<BlockInfo> buildSpecification(BlockInfo blockInfo) {
		return new Specification<BlockInfo>() {
			@Override
			public Predicate toPredicate(Root<BlockInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//				query.orderBy(cb.desc(root.get("varDate")));

				List<Predicate> predicates = new LinkedList<>();
				if (!Tools.empty(blockInfo.getNumber())) {
					predicates.add(cb.equal(root.get("blockNumber"), blockInfo.getNumber()));
				}
				if (!Tools.empty(blockInfo.getHash())) {
					predicates.add(cb.equal(root.get("hash"), blockInfo.getHash()));
				}
//				if (!Tools.empty(debugRecord.getRecordTime())) {
//					predicates.add(cb.greaterThanOrEqualTo(root.get("recordTime"), //
//							debugRecord.getRecordTime()));
//				}
//				if (!Tools.empty(debugRecord.getRecordTime2())) {
//					predicates.add(cb.lessThan(root.get("recordTime"), //
//							debugRecord.getRecordTime2()));
//				}
//				if (!Tools.empty(debugRecord.getStartIndex())) {
//					predicates.add(cb.greaterThan(root.get("id"), debugRecord.getStartIndex()));
//				}
				return cb.and(predicates.toArray(new Predicate[0]));
			}
		};
	}

	@SuppressWarnings("serial")
	public static Specification<TransactionInfo> buildSpecification(TransactionInfo transactionInfo) {
		return new Specification<TransactionInfo>() {
			@Override
			public Predicate toPredicate(Root<TransactionInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//				query.orderBy(cb.desc(root.get("varDate")));

				List<Predicate> predicates = new LinkedList<>();
				if (!Tools.empty(transactionInfo.getFrom())) {
					predicates.add(cb.equal(root.get("from"), transactionInfo.getFrom()));
				}
				if (!Tools.empty(transactionInfo.getTo())) {
					predicates.add(cb.equal(root.get("to"), transactionInfo.getTo()));
				}
				if (!Tools.empty(transactionInfo.getBlockHash())) {
					predicates.add(cb.equal(root.get("blockHash"), transactionInfo.getBlockHash()));
				}
				if (!Tools.empty(transactionInfo.getBlockNumber())) {
					predicates.add(cb.equal(root.get("blockNumber"), transactionInfo.getBlockNumber()));
				}
				if (!Tools.empty(transactionInfo.getHash())) {
					predicates.add(cb.equal(root.get("hash"), transactionInfo.getHash()));
				}
//				if (!Tools.empty(debugRecord.getRecordTime2())) {
//					predicates.add(cb.lessThan(root.get("recordTime"), //
//							debugRecord.getRecordTime2()));
//				}
//				if (!Tools.empty(debugRecord.getStartIndex())) {
//					predicates.add(cb.greaterThan(root.get("id"), debugRecord.getStartIndex()));
//				}
				return cb.and(predicates.toArray(new Predicate[0]));
			}
		};
	}

	@SuppressWarnings("serial")
	public static Specification<ContractInfo> buildSpecification(ContractInfo contractInfo) {
		return new Specification<ContractInfo>() {
			@Override
			public Predicate toPredicate(Root<ContractInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//				query.orderBy(cb.desc(root.get("varDate")));

				List<Predicate> predicates = new LinkedList<>();

				if (!Tools.empty(contractInfo.getTxHash())) {
					predicates.add(cb.equal(root.get("txHash"), contractInfo.getTxHash()));
				}
//				if (!Tools.empty(debugRecord.getRecordTime2())) {
//					predicates.add(cb.lessThan(root.get("recordTime"), //
//							debugRecord.getRecordTime2()));
//				}
//				if (!Tools.empty(debugRecord.getStartIndex())) {
//					predicates.add(cb.greaterThan(root.get("id"), debugRecord.getStartIndex()));
//				}
				return cb.and(predicates.toArray(new Predicate[0]));
			}
		};
	}

	@SuppressWarnings("serial")
	public static Specification<UserInfo> buildSpecification(UserInfo usrInfo) {
		return new Specification<UserInfo>() {
			@Override
			public Predicate toPredicate(Root<UserInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//				query.orderBy(cb.desc(root.get("varDate")));

				List<Predicate> predicates = new LinkedList<>();

				if (!Tools.empty(usrInfo.getUserType())) {
					predicates.add(cb.equal(root.get("userType"), usrInfo.getUserType()));
				}
//				if (!Tools.empty(debugRecord.getRecordTime2())) {
//					predicates.add(cb.lessThan(root.get("recordTime"), //
//							debugRecord.getRecordTime2()));
//				}
//				if (!Tools.empty(debugRecord.getStartIndex())) {
//					predicates.add(cb.greaterThan(root.get("id"), debugRecord.getStartIndex()));
//				}
				predicates.add(cb.notEqual(root.get("userType"), UserType.SUPERADMIN));
				return cb.and(predicates.toArray(new Predicate[0]));
			}
		};
	}

}
